import java.util.ArrayList;
import java.util.List;

public class FractalPicture {
	private static class Segment {
		private final int x1;
		private final int y1;
		private final int x2;
		private final int y2;

		private Segment(int x1, int y1, int x2, int y2) {
			this.x1 = x1;
			this.y1 = y1;
			this.x2 = x2;
			this.y2 = y2;
		}
	}

	public double getLength(int x1, int y1, int x2, int y2) {
		List<Segment> nonFinal = new ArrayList<Segment>();
		List<Segment> finalSegments = new ArrayList<Segment>();
		nonFinal.add(new Segment(0, 0, 0, 243));
		for (int i = 243; i > 1; i /= 3) {
			List<Segment> nextNonFinal = new ArrayList<Segment>();
			for (Segment segment : nonFinal) {
				int dx = (segment.x2 - segment.x1) / 3;
				int dy = (segment.y2 - segment.y1) / 3;
				int x = segment.x1 + 2 * dx;
				int y = segment.y1 + 2 * dy;
				finalSegments.add(new Segment(segment.x1, segment.y1, x, y));
				nextNonFinal.add(new Segment(x, y, x + dx, y + dy));
				nextNonFinal.add(new Segment(x, y, x + dy, y + dx));
				nextNonFinal.add(new Segment(x, y, x - dy, y - dx));
			}
			nonFinal = nextNonFinal;
		}
		x1 *= 3;
		y1 *= 3;
		x2 *= 3;
		y2 *= 3;
		double result = 0;
		for (Segment segment : finalSegments) {
			if (segment.x1 == segment.x2 && segment.x1 <= x2 && segment.x1 >= x1)
				result += Math.max(0, Math.min(y2, Math.max(segment.y1, segment.y2)) - Math.max(y1, Math.min(segment.y1, segment.y2)));
			else if (segment.y1 == segment.y2 && segment.y1 <= y2 && segment.y1 >= y1)
				result += Math.max(0, Math.min(x2, Math.max(segment.x1, segment.x2)) - Math.max(x1, Math.min(segment.x1, segment.x2)));
		}
		for (Segment segment : nonFinal) {
			if (segment.x1 >= x1 && segment.x2 >= x1 && segment.x1 <= x2 && segment.x2 <= x2 &&
				segment.y1 >= y1 && segment.y2 >= y1 && segment.y1 <= y2 && segment.y2 <= y2)
			{
				result += 1 + 2./ 3 * 494;
			}
		}
		return result / 3;
	}


// BEGIN CUT HERE
	public static void main(String[] args) {
		if (args.length == 0) {
			FractalPictureHarness.run_test(-1);
		} else {
			for (int i=0; i<args.length; ++i)
				FractalPictureHarness.run_test(Integer.valueOf(args[i]));
		}
	}
// END CUT HERE
}

// BEGIN CUT HERE
class FractalPictureHarness {
	public static void run_test(int casenum) {
		if (casenum != -1) {
			if (runTestCase(casenum) == -1)
				System.err.println("Illegal input! Test case " + casenum + " does not exist.");
			return;
		}
		
		int correct = 0, total = 0;
		for (int i=0;; ++i) {
			int x = runTestCase(i);
			if (x == -1) {
				if (i >= 100) break;
				continue;
			}
			correct += x;
			++total;
		}
		
		if (total == 0) {
			System.err.println("No test cases run.");
		} else if (correct < total) {
			System.err.println("Some cases FAILED (passed " + correct + " of " + total + ").");
		} else {
			System.err.println("All " + total + " tests passed!");
		}
	}
	
	static final double MAX_DOUBLE_ERROR = 1E-9;
	static boolean compareOutput(double expected, double result){ if(Double.isNaN(expected)){ return Double.isNaN(result); }else if(Double.isInfinite(expected)){ if(expected > 0){ return result > 0 && Double.isInfinite(result); }else{ return result < 0 && Double.isInfinite(result); } }else if(Double.isNaN(result) || Double.isInfinite(result)){ return false; }else if(Math.abs(result - expected) < MAX_DOUBLE_ERROR){ return true; }else{ double min = Math.min(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR)); double max = Math.max(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR)); return result > min && result < max; } }
	static double relativeError(double expected, double result) { if (Double.isNaN(expected) || Double.isInfinite(expected) || Double.isNaN(result) || Double.isInfinite(result) || expected == 0) return 0; return Math.abs(result-expected) / Math.abs(expected); }
	
	static String formatResult(double res) {
		return String.format("%.10g", res);
	}
	
	static int verifyCase(int casenum, double expected, double received) { 
		System.err.print("Example " + casenum + "... ");
		if (compareOutput(expected, received)) {
			System.err.print("PASSED");
			double rerr = relativeError(expected, received);
			if (rerr > 0) System.err.printf(" (relative error %g)", rerr);
			System.err.println();
			return 1;
		} else {
			System.err.println("FAILED");
			System.err.println("    Expected: " + formatResult(expected)); 
			System.err.println("    Received: " + formatResult(received)); 
			return 0;
		}
	}

	static int runTestCase(int casenum) {
		switch(casenum) {
		case 0: {
			int x1                    = -1;
			int y1                    = 0;
			int x2                    = 1;
			int y2                    = 53;
			double expected__         = 53.0;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}
		case 1: {
			int x1                    = 1;
			int y1                    = 1;
			int x2                    = 10;
			int y2                    = 10;
			double expected__         = 0.0;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}
		case 2: {
			int x1                    = -10;
			int y1                    = 54;
			int x2                    = 10;
			int y2                    = 55;
			double expected__         = 21.0;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}
		case 3: {
			int x1                    = 14;
			int y1                    = 45;
			int x2                    = 22;
			int y2                    = 54;
			double expected__         = 2999.0;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}

		// custom cases

/*      case 4: {
			int x1                    = ;
			int y1                    = ;
			int x2                    = ;
			int y2                    = ;
			double expected__         = ;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}*/
/*      case 5: {
			int x1                    = ;
			int y1                    = ;
			int x2                    = ;
			int y2                    = ;
			double expected__         = ;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}*/
/*      case 6: {
			int x1                    = ;
			int y1                    = ;
			int x2                    = ;
			int y2                    = ;
			double expected__         = ;

			return verifyCase(casenum, expected__, new FractalPicture().getLength(x1, y1, x2, y2));
		}*/
		default:
			return -1;
		}
	}
}

// END CUT HERE
